//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V0.2.0
/********************************************************
    说明：
    1、先注册个总线，最大3个。每个总线上可挂多个SPI设备。每个总线的速率可动态调整。(挂在一起的设备引脚必须一样)
    2、每个外挂的SPI设备自行提供收发缓存和片选。
    3、每个总线均会自动提供给SPI实时状态和互斥锁状态。
    4、支持普通收发数据、中断收发数据、DMA收发数据。
    5、支持片选软件控制和硬件控制。
    6、增加SPI使能开关，可节省空间。
    7、基于STM32F10X标准库V3.6.0
**********************************************************/

#ifndef __SPI_BSP_H__
#define __SPI_BSP_H__

#include "../DMA_BSP/dma_bsp.h"


#define WHT_SPI1_Name    "WHT_SPI1"
#define WHT_SPI2_Name    "WHT_SPI2"
#define WHT_SPI3_Name    "WHT_SPI3"

/*SPI发送或接收枚举*/
typedef enum
{
    SPI_WO = 0,//只发送模式
    SPI_RO = 1,//只接收模式
    SPI_RW = 2,//收发模式
}WHT_SPI_Mode_enum;

/*SPI状态枚举*/
typedef enum
{
    SPI_No_Error      = 0,//无错误码
    SPI_BUS_Error     = 1,//总线错误
    SPI_Rx_Over_Error = 2,//接收溢出
    SPI_CRC_Error     = 3,//CRC校验错误
}WHT_SPI_BUS_State_enum;

/*SPI锁枚举*/
typedef enum
{
    SPI_Unlock = 0,
    SPI_Lock   = 1,
}WHT_SPI_BUS_Lock_enum;

/*SPI IO状态枚举*/
typedef enum
{
    SPI_IO_Low = 0,
    SPI_IO_Hig = 1,
}WHT_SPI_IO_State_enum;

/*SPI工作模式枚举*/
typedef enum
{
    SPI_Work_Mode0 = 0,
    SPI_Work_Mode1 = 1,
    SPI_Work_Mode2 = 2,
    SPI_Work_Mode3 = 3,
}WHT_SPI_BUS_Work_Mode_enum;


/*SPI字长枚举*/
typedef enum
{
    SPI_8Bit_Wide  = 8, //1Byte
    SPI_16Bit_Wide = 16,//2Byte
}WHT_SPI_BUS_Bit_Wide_enum;

/*SPI片选枚举*/
typedef enum
{
    Soft_NSS = 0,//手动模式
    Hard_NSS = 1,//硬件自动模式
}WHT_SPI_NSS_enum;

/*SPI时钟分频枚举*/
typedef enum
{//APB1 Default =48Mhz APB2 Default =72Mhz
    APBx_DIV2   = SPI_BaudRatePrescaler_2,  //时钟源APBx的2分频
    APBx_DIV4   = SPI_BaudRatePrescaler_4,  //时钟源APBx的4分频
    APBx_DIV8   = SPI_BaudRatePrescaler_8,  //时钟源APBx的8分频
    APBx_DIV16  = SPI_BaudRatePrescaler_16, //时钟源APBx的16分频
    APBx_DIV32  = SPI_BaudRatePrescaler_32, //时钟源APBx的32分频
    APBx_DIV64  = SPI_BaudRatePrescaler_64, //时钟源APBx的64分频
    APBx_DIV128 = SPI_BaudRatePrescaler_128,//时钟源APBx的128分频
    APBx_DIV256 = SPI_BaudRatePrescaler_256,//时钟源APBx的256分频
}WHT_SPI_BUS_Div_enum;

/*SPI总线配置结构体*/
typedef struct
{
    unsigned char Master_Slave;          //0主机 1从机
    WHT_SPI_BUS_Work_Mode_enum Work_Mode;//工作模式
    WHT_SPI_BUS_Div_enum Clock_Div;      //SPI频率
    unsigned char MSB_LSB;               //0 MSB 1 LSB
    WHT_SPI_BUS_Bit_Wide_enum Bit_Wide;  //位宽
    WHT_SPI_NSS_enum NSS;                //手动片选与硬件自动片选
    uint8_t IT_PreemptionPriority;       //抢占优先级
    uint8_t IT_SubPriority;              //子优先级
}WHT_SPI_BUS_Config_t;

/*SPI总线结构体*/
typedef struct
{
    char* Name;                        //总线名字
    WHT_SPI_BUS_Config_t Config;       //总线配置信息
    const WHT_SPI_BUS_Lock_enum Mutex; //驱动锁,自动上锁与解锁
    const WHT_SPI_BUS_State_enum State;//错误标志,自动清零
}WHT_SPI_BUS_t;

/*SPI缓存结构体*/
typedef struct
{
    WHT_SPI_Mode_enum Dir; //读写方向
    unsigned int Buffer_Count;//个数
    unsigned char* Tx_Buffer; //缓存
    unsigned char* Rx_Buffer; //接收缓存，不足8bit按8bit，不足16bit按16bit，不足32bit按32bit
    void (*Set_NSS_State_CB)(WHT_SPI_IO_State_enum state);
    void (*TRx_Finish_IT_CB)(void);//发送接收完成中断回调函数
}WHT_SPI_Cache_t;

/*SPI回调函数结构体*/
typedef struct
{
    WHT_SPI_BUS_t* (*Register)(char* name, WHT_SPI_BUS_Config_t* config, void (*gpio_init_callback)(void));
    void (*Unregister)(WHT_SPI_BUS_t* bus);
    ////void (*Set_Rate)(WHT_SPI_BUS_t* bus);
    void (*Read_Write)(WHT_SPI_BUS_t* bus, WHT_SPI_Cache_t* cache);
    void (*Read_Write_IT)(WHT_SPI_BUS_t* bus, WHT_SPI_Cache_t* cache);
    void (*Read_Write_DMA)(WHT_SPI_BUS_t* bus, WHT_SPI_Cache_t* cache);
}WHT_SPI_BUS_OPS_t;

/*全局常量*/
extern const WHT_SPI_BUS_OPS_t WHT_SPI_BUS_OPS;

#endif /*__SPI_BSP_H__*/
